package br.usp.tuf.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public final class GeradorAleatorio {
	
	private static final String ALFABETO = "abcdefghijklmnopqrstuvwxyzçABCDEFGHIJKLMNOPQRSTUVWXYZÇ1234567890";
	
	private static List<Class<?>> tiposPrimitivos;
	
	// A semente utilizada para a geração aleatória será System.currentTimeMilis().
	private static final Random RANDOM = new Random();	
	
	private GeradorAleatorio() {
		super();
	}
	
	public static byte getByte() {
		return (byte) getInt(Byte.MIN_VALUE, Byte.MAX_VALUE);
	}
	
	public static byte getByte(byte limiteInferior, byte limitePosterior) {
		return (byte) getInt(limiteInferior, limitePosterior);
	}
	
	public static short getShort() {
		return (short) getInt(Short.MIN_VALUE, Short.MAX_VALUE);
	}
	
	public static short getShort(short limiteInferior, short limitePosterior) {
		return (short) getInt(limiteInferior, limitePosterior);
	}
	
	public static int getInt() {
		return RANDOM.nextInt();
	}
	
	public static int getInt(int limiteInferior, int limitePosterior) {
		int tamanhoDoLimite = limitePosterior - limiteInferior;
		return limiteInferior + RANDOM.nextInt(tamanhoDoLimite + 1);
	}
	
	public static long getLong() {
		return RANDOM.nextLong();
	}
	
	public static long getLong(long limiteInferior, long limitePosterior) {
		long tamanhoDoLimite = limitePosterior - limiteInferior;
		return limiteInferior + (long) (Math.random() * tamanhoDoLimite);
	}
	
	public static float getFloat() {
		return RANDOM.nextFloat();
	}
	
	public static float getFloat(float limiteInferior, float limitePosterior) {
		float tamanhoDoLimite = limitePosterior - limiteInferior;
		return limiteInferior + (float) (Math.random() * tamanhoDoLimite);
	}
	
	public static double getDouble() {
		return RANDOM.nextDouble();
	}
	
	public static double getDouble(double limiteInferior, double limitePosterior) {
		double tamanhoDoLimite = limitePosterior - limiteInferior;
		return limiteInferior + (Math.random() * tamanhoDoLimite);
	}
	
	public static char getChar() {
		return ALFABETO.charAt(RANDOM.nextInt(ALFABETO.length()));
	}
	
	public static String getString(int tamanhoMaximo) {
		final StringBuffer sb = new StringBuffer();
		for (int contador = 0; contador < tamanhoMaximo; contador++) {
			sb.append(getChar());
		}
		return sb.toString();
	}
	
	public static boolean getBoolean() {
		return RANDOM.nextBoolean();
	}

	private static List<Class<?>> getTiposPrimitivos() {
		if (tiposPrimitivos == null) {
			tiposPrimitivos = new ArrayList<Class<?>>();
			tiposPrimitivos.add(byte.class);
			tiposPrimitivos.add(Byte.class);
			tiposPrimitivos.add(short.class);
			tiposPrimitivos.add(Short.class);
			tiposPrimitivos.add(int.class);
			tiposPrimitivos.add(Integer.class);
			tiposPrimitivos.add(long.class);
			tiposPrimitivos.add(Long.class);
			tiposPrimitivos.add(float.class);
			tiposPrimitivos.add(Float.class);
			tiposPrimitivos.add(double.class);
			tiposPrimitivos.add(Double.class);
			tiposPrimitivos.add(boolean.class);
			tiposPrimitivos.add(Boolean.class);
			tiposPrimitivos.add(char.class);
			tiposPrimitivos.add(Character.class);
			tiposPrimitivos.add(String.class);
		}
		return tiposPrimitivos;
	}

	public static boolean isPrimitivo(String valor) {
		boolean isPrimitivo = false;
		for (Class<?> classe : GeradorAleatorio.getTiposPrimitivos()) {
			if (classe.getName().equals(valor)) {
				isPrimitivo = true;
				break;
			}
		}
		return isPrimitivo;
	}
	
	public static boolean isPrimitivo(Class<?> classe) {
		return GeradorAleatorio.getTiposPrimitivos().contains(classe);
	}
	
	public static Object get(Object parametro) {
		Object retorno = null;
		if (parametro.equals(parametro instanceof String ? byte.class.getName() : byte.class)) {
			retorno = getByte();
		} else if (parametro.equals(parametro instanceof String ? Byte.class.getName() : Byte.class)) {
			retorno = new Byte(getByte());
		} else if (parametro.equals(parametro instanceof String ? short.class.getName() : short.class)) {
			retorno = getShort();
		} else if (parametro.equals(parametro instanceof String ? Short.class.getName() : Short.class)) {
			retorno = new Short(getShort());
		} else if (parametro.equals(parametro instanceof String ? int.class.getName() : int.class)) {
			retorno = getInt();
		} else if (parametro.equals(parametro instanceof String ? Integer.class.getName() : Integer.class)) {
			retorno = new Integer(getInt());
		} else if (parametro.equals(parametro instanceof String ? long.class.getName() : long.class)) {
			retorno = getLong();
		} else if (parametro.equals(parametro instanceof String ? Long.class.getName() : Long.class)) {
			retorno = new Long(getLong());
		} else if (parametro.equals(parametro instanceof String ? double.class.getName() : double.class)) {
			retorno = getDouble();
		} else if (parametro.equals(parametro instanceof String ? Double.class.getName() : Double.class)) {
			retorno = new Double(getDouble());
		} else if (parametro.equals(parametro instanceof String ? boolean.class.getName() : boolean.class)) {
			retorno = getBoolean();
		} else if (parametro.equals(parametro instanceof String ? Boolean.class.getName() : Boolean.class)) {
			retorno = new Boolean(getBoolean());
		} else if (parametro.equals(parametro instanceof String ? char.class.getName() : char.class)) {
			retorno = getChar();
		} else if (parametro.equals(parametro instanceof String ? Character.class.getName() : Character.class)) {
			retorno = new Character(getChar());
		} else if (parametro.equals(parametro instanceof String ? String.class.getName() : String.class)) {
			retorno = getString(100);
		}
		return retorno;
	}
	
	
}
